package com.epin.business.commons.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.epin.base.enums.commons.ForeignKeyEnum;
import com.epin.business.commons.dao.ForeignKeyMapper;
import com.epin.business.commons.entity.ForeignKey;
import com.epin.business.commons.entity.ForeignKeyCols;
import com.epin.business.commons.entity.bo.ForeignKeyField;
import com.epin.business.commons.entity.bo.ForeignKeyNormal;
import com.epin.business.commons.entity.vo.ForeignKeyParam;
import com.epin.business.commons.service.ForeignKeyService;
import com.epin.business.commons.service.RedisService;
import com.epin.business.system.entity.bo.UserNormal;
import com.feilong.core.Validator;


/**
 * <p>
 * 表伪外键记录表 服务实现类
 * </p>
 *
 * @author fujiajun
 * @since 2017-09-08
 */
@Service
public class ForeignKeyServiceImpl extends ServiceImpl<ForeignKeyMapper, ForeignKey> implements ForeignKeyService {
	
	private final static String REDIS_SUCCESS = "OK";
	
	@Autowired
	private RedisService redisService;

	
	/**
	 * <p>实现分页查找</p>
	 * 
	 * <p>
	 * 	参数表可填参数：
	 * 		<p>keyword 关键字</p>
	 * </p>
	 */
	@Override
	public Page<ForeignKeyNormal> selectForeignKeysPage(Integer pageNumber, Integer pageSize, Map<String, Object> params) {
		// 构造分页器
		Page<ForeignKeyNormal> page = new Page<>(pageNumber, pageSize);
						
		// 获取查询结果
		List<ForeignKeyNormal> list = baseMapper.selectForeignKeyVoList(page, params);
						
		// 打包数据
		page.setRecords(list);
					
		return page;
	}

	

	/**
	 * <p>通过表名获取约束数据</p>
	 */
	@Override
	public List<ForeignKeyNormal> selectForeignKeysByTableName(String tableName) {
		
		if (Validator.isNullOrEmpty(tableName)) {
			return null;
		}
		
		List<ForeignKeyNormal> foreignKeys = getValueFromRedis(tableName);
		
		if (Validator.isNullOrEmpty(foreignKeys)) {
			// 查询数据库一次
			foreignKeys = baseMapper.selectForeignKeyByTable(tableName);
			
			setValueToRedis(tableName, foreignKeys);
		}
		
		return foreignKeys;
	}


	
	/**
	 * <p>添加外键约束</p>
	 */
	@Override
	public boolean insertForeignKey(ForeignKeyParam fParam, UserNormal operator) {
		// TODO Auto-generated method stub
		return false;
	}


	
	/**
	 * <p>根据id数组删除约束</p>
	 */
	@Override
	public boolean deleteForeignKeysByIds(List<Integer> ids) {
		
		if (Validator.isNullOrEmpty(ids)) {
			return false;
		}
		
		// 清理缓存
		deleteValuesInRedis(ids);
		
		// 再执行操作
		return deleteBatchIds(ids);
	}


	
	/**
	 * <p>判断指定表的某条记录是否被引用</p>
	 */
	@Override
	public boolean checkRecordIsQuoted(String tableName, String id) {
		
		// 判断参数
		if (Validator.isNullOrEmpty(tableName) || Validator.isNullOrEmpty(id)) {
			return false;
		}
		
		// 查询约束数据
		List<ForeignKeyNormal> foreignKeys = this.selectForeignKeysByTableName(tableName);
		if (Validator.isNullOrEmpty(foreignKeys)) {
			return false;
		}
		
		// 计算引用数判断是否引用
		for (ForeignKeyNormal foreignKey : foreignKeys) {
			
			// 检查删除状态是否为RESTRICT或NOACTION，否则跳过检查
			ForeignKeyEnum style = ForeignKeyEnum.getStyle(foreignKey.getDeleteType());
			if (style != ForeignKeyEnum.RESTRICT && style != ForeignKeyEnum.NOACTION) {
				continue;
			}
			
			// 检查是否有约束字段，没有则跳过检查
			if (Validator.isNullOrEmpty(foreignKey.getCols())) {
				continue;
			}
			
			// 构造字段名列表
			List<ForeignKeyField> fields = new ArrayList<>();
			for (ForeignKeyCols col : foreignKey.getCols()) {
				fields.add(new ForeignKeyField(col.getField(), col.getReferenceField()));
			}
			
			int count = 0;
			
			try {
				count = baseMapper.countTableFieldRecords(foreignKey.getTable(), foreignKey.getReferenceTable(), fields, id);
			} catch (RuntimeException e) {
				e.printStackTrace();
			}
			
			if (count > 0) {
				return true;
			}
		}
		
		return false;
	}
	
	
	/**
	 * <p>设置数据到Redis里</p>
	 * 
	 * @param key 标识
	 * @param foreignKeys 约束数组
	 * 
	 * @return boolean
	 * 
	 * @author fujiajun
	 * @since 2017-09-09
	 */
	private boolean setValueToRedis(String key, List<ForeignKeyNormal> foreignKeys){
		
		if (Validator.isNullOrEmpty(key)) {
			return false;
		}
		
		String value = Validator.isNotNullOrEmpty(foreignKeys) ? JSON.toJSONString(foreignKeys) : "";
		
		String result = redisService.set(key, value);
		
		return result.equals(REDIS_SUCCESS);
	}
	
	
	/**
	 * <p>从Redis里获取数据</p>
	 * 
	 * @param key 标识
	 * 
	 * @return List<>
	 * 
	 * @author fujiajun
	 * @since 2017-09-09
	 */
	private List<ForeignKeyNormal> getValueFromRedis(String key){
		
		if (Validator.isNullOrEmpty(key)) {
			return null;
		}
		
		String value = redisService.get(key);
		
		return Validator.isNotNullOrEmpty(value) ? JSON.parseObject(value, new TypeReference<List<ForeignKeyNormal>>(){}) : null;
	}
	
	
	/**
	 * <p>清理缓存数据</p>
	 * 
	 * @param ids 数据数组
	 * 
	 * @return boolean
	 * 
	 * @author fujiajun
	 * @since 2017-09-09
	 */
	private boolean deleteValuesInRedis(List<Integer> ids){
		
		if (Validator.isNullOrEmpty(ids)) {
			return false;
		}
		
		for (Integer id : ids) {
			
			String table = baseMapper.selectTableById(id);
			
			redisService.del(table);
		}
		
		return true;
	}
	
}
